#include "ccopenglwidget.h"

#include <QTimer>
#include <QPainter>
#include <QDateTime>
#include <QPropertyAnimation>

CCOpenGLWidget::CCOpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
    , secondAnimation(nullptr)
    , m_monthAngle(0)
    , m_dayAngle(0)
    , m_weekAngle(0)
    , m_timeAngle(0)
    , m_hourAngle(0)
    , m_minuteAngle(0)
    , m_secondAngle(0)
    , m_daysInMonth(0)
    , m_year(0)
{
    // 定时器
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &CCOpenGLWidget::slotUpdateDateTime);
    timer->start(1000);

    secondAnimation = new QPropertyAnimation(this, "secondAngle", this);
    secondAnimation->setDuration(300); // 0.3秒
    QEasingCurve easingCurve(QEasingCurve::OutElastic);
    easingCurve.setAmplitude(0.6);
    easingCurve.setPeriod(0.6);
    secondAnimation->setEasingCurve(easingCurve);
    slotUpdateDateTime();
}

CCOpenGLWidget::~CCOpenGLWidget()
{

}

void CCOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
    f->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  // 设置窗体背景色
    int w = this->width();
    int h = this->height();
    glOrtho(0.0, w, h, 0.0, -1.0, 1.0);
}

void CCOpenGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void CCOpenGLWidget::paintGL()
{
    QPainter painter(this);
    // 开启反锯齿
    painter.setRenderHint(QPainter::TextAntialiasing);
    // 锚点居中
    painter.translate(width() / 2, height() / 2);
    // 设置字体
    QFont font("微软雅黑", 10);
    painter.setFont(font);

    drawDial(painter);
    drawYear(painter);
    drawMonth(painter);
    drawDay(painter);
    drawWeek(painter);
    drawTime(painter);
    drawHour(painter);
    drawMinute(painter);
    drawSecond(painter);
}

void CCOpenGLWidget::slotUpdateDateTime()
{
    // 计算角度
    QDateTime dateTime = QDateTime::currentDateTime();
    m_year = dateTime.date().year();
    m_daysInMonth = dateTime.date().daysInMonth();

    int month = dateTime.date().month();
    int day = dateTime.date().day();
    int week = dateTime.date().dayOfWeek();
    int hour = dateTime.time().hour();
    int minute = dateTime.time().minute();
    int second = dateTime.time().second();

    // 计算角度
    qreal newMonthAngle = 30.0 * month;
    qreal newDayAngle = 360.0 / m_daysInMonth * day;
    qreal newWeekAngle = 360.0 / 7 * week;
    qreal newTimeAngle = 30.0 * ((hour / 2 + (hour % 2 == 1 ? 1 : 0)) % 12);
    qreal newHourAngle = 15.0 * hour;
    qreal newMinuteAngle = 6.0 * minute;
    qreal newSecondAngle = 6.0 * second;

    m_monthAngle = newMonthAngle;
    m_dayAngle = newDayAngle;
    m_weekAngle = newWeekAngle;
    m_timeAngle = newTimeAngle;
    m_hourAngle = newHourAngle;
    m_minuteAngle = newMinuteAngle;

    // 播放秒钟动画
    m_secondAngle = m_secondAngle == 360 ? 0 : m_secondAngle;
    newSecondAngle = newSecondAngle == 0 ? 360 : newSecondAngle;
    secondAnimation->setStartValue(m_secondAngle);
    secondAnimation->setEndValue(newSecondAngle);
    secondAnimation->start();
}

void CCOpenGLWidget::drawDial(QPainter &painter)
{
    painter.save();
    painter.setPen(Qt::white);
    painter.drawLine(-38, 12, 500, 12);
    painter.restore();
}

void CCOpenGLWidget::drawYear(QPainter &painter)
{
    static QStringList numberString = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
    QString yearString;
    int year = m_year;
    while (year)
    {
        yearString.push_front(numberString[year % 10]);
        year /= 10;
    }
    painter.save();
    painter.setPen(Qt::white);
    painter.drawText(-50, -50, 100, 100, Qt::AlignCenter, yearString + "年");
    painter.restore();
}

void CCOpenGLWidget::drawMonth(QPainter &painter)
{
    static QStringList s =
    {
        "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_monthAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(50, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawDay(QPainter &painter)
{
    static QStringList s =
    {
        "一日", "二日", "三日", "四日", "五日", "六日", "七日", "八日", "九日", "十日",
        "十一日", "十二日", "十三日", "十四日", "十五日", "十六日", "十七日", "十八日", "十九日", "二十日",
        "二十一日", "二十二日", "二十三日", "二十四日", "二十五日", "二十六日", "二十七日", "二十八日", "二十九日", "三十日",
        "三十一日",
    };
    // 每个月的天数不一样，所以此处不能用static
    qreal r = 360.0 / m_daysInMonth;
    for (int i = 0; i < m_daysInMonth; ++i)
    {
        painter.save();
        qreal rota = -r * i + m_dayAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(110, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawWeek(QPainter &painter)
{
    static QStringList s =
    {
        "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六",
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_weekAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(190, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawTime(QPainter &painter)
{
    static QStringList s =
    {
        "子时", "丑时", "寅时", "卯时", "辰时", "巳时", "午时", "未时", "申时", "酉时", "戌时", "亥时",
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_timeAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(250, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawHour(QPainter &painter)
{
    static QStringList s =
    {
        "零时", "一时", "二时", "三时", "四时", "五时", "六时", "七时", "八时", "九时", "十时", "十一时",
        "十二时", "十三时", "十四时", "十五时", "十六时", "十七时", "十八时", "十九时", "二十时", "二十一时", "二十二时", "二十三时",
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_hourAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(290, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawMinute(QPainter &painter)
{
    static QStringList s =
    {
        "零分", "一分", "二分", "三分", "四分", "五分", "六分", "七分", "八分", "九分",
        "十分", "十一分", "十二分", "十三分", "十四分", "十五分", "十六分", "十七分", "十八分", "十九分",
        "二十分", "二十一分", "二十二分", "二十三分", "二十四分", "二十五分", "二十六分", "二十七分", "二十八分", "二十九分",
        "三十分", "三十一分", "三十二分", "三十三分", "三十四分", "三十五分", "三十六分", "三十七分", "三十八分", "三十九分",
        "四十分", "四十一分", "四十二分", "四十三分", "四十四分", "四十五分", "四十六分", "四十七分", "四十八分", "四十九分",
        "五十分", "五十一分", "五十二分", "五十三分", "五十四分", "五十五分", "五十六分", "五十七分", "五十八分", "五十九分",
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_minuteAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(370, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

void CCOpenGLWidget::drawSecond(QPainter &painter)
{
    static QStringList s =
    {
        "零秒", "一秒", "二秒", "三秒", "四秒", "五秒", "六秒", "七秒", "八秒", "九秒",
        "十秒", "十一秒", "十二秒", "十三秒", "十四秒", "十五秒", "十六秒", "十七秒", "十八秒", "十九秒",
        "二十秒", "二十一秒", "二十二秒", "二十三秒", "二十四秒", "二十五秒", "二十六秒", "二十七秒", "二十八秒", "二十九秒",
        "三十秒", "三十一秒", "三十二秒", "三十三秒", "三十四秒", "三十五秒", "三十六秒", "三十七秒", "三十八秒", "三十九秒",
        "四十秒", "四十一秒", "四十二秒", "四十三秒", "四十四秒", "四十五秒", "四十六秒", "四十七秒", "四十八秒", "四十九秒",
        "五十秒", "五十一秒", "五十二秒", "五十三秒", "五十四秒", "五十五秒", "五十六秒", "五十七秒", "五十八秒", "五十九秒",
    };
    static qreal r = 360.0 / s.size();
    for (int i = 0; i < s.size(); ++i)
    {
        painter.save();
        qreal rota = -r * i + m_secondAngle;
        painter.setPen(Qt::white);
        painter.rotate(rota);
        painter.drawText(450, -50, 100, 100, Qt::AlignLeft | Qt::AlignVCenter, s.at(i));
        painter.restore();
    }
}

qreal CCOpenGLWidget::secondAngle() const
{
    return m_secondAngle;
}

void CCOpenGLWidget::setSecondAngle(qreal value)
{
    m_secondAngle = value;
    update();
}
